package com.fang.springboot.controller;

import com.fang.springboot.service.HelloService;
import com.fang.springboot.service.ThreeService;
import com.fang.springboot.service.TwoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {

    /**
     * 这里的helloservice 没有transactional注解，也就是没有aop的拦截处理，默认就是单例对象
     */
    @Autowired
    private HelloService service;

    /**
     * 使用了transactional注解，也就是景
     */
    @Autowired
    private TwoService twoService;

    @Autowired
    private ThreeService threeService;

    /**
     * 对web层的调用是通过 方法反射的形式调用的， 也就是我们之前所说的HandlerMethod
     *
     * @return
     */
    @RequestMapping("/index")
    public String hello() {
        return "index";
    }


    /**
     * 测试事物配置在class上面指定过程
     *
     * @return
     */
    @RequestMapping("/transactionClass")
    public String transactionClass() {
        //方法执行前
        System.out.println("方法执行前 helloService的类型为==" + twoService.getClass());
        twoService.hello();
        System.out.println("方法执行后helloService的类型为==" + twoService.getClass());
        return "index";
    }


    /**
     * 测试事物配置在方法上面
     *
     * @return
     */
    @RequestMapping("/transactionMethod")
    public String transactionMethod() {
        //方法执行前
        System.out.println("方法执行前 helloService的类型为==" + threeService.getClass());
        threeService.hello();
        System.out.println("方法执行后helloService的类型为==" + threeService.getClass());
        return "index";
    }

    /**
     * 原因是什么
     *
     * spring对bean的初始化 会根据条件执行 bean的后置处理器 ，根据bean的类型，产生不同的代理类
     *
     * 对象
     *    代理对象  和  advice（增强/通知）
     *
     * 对于transactional来说， 通过后置处理器 产生的就是代理对象  advice 可以理解就是 TransactionInterceptor;
     *
     * 所以我们现在理一下思路 。对于添加了@transactional注解的对象或方法来说 会导致bean在初始化过程中经过后置处理器的处理
     * 产生代理bean ，这个代理bean在方法的执行（前后）会去调用 TransactionInterceptor#invoke方法，在这里方法内部
     */


}
